package com.bluesky.dreamer.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.transform.ResultTransformer;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.sitech.biportal.util.StringUtil;

/**
 * @author handong
 * @category -09-18
 *           此类扩展自org.springframework.orm.hibernate3.support.HibernateDaoSupport
 *           此Dao包含了很多便利的方法，依赖于spring中的hibernate支持使用时：
 *           要设入sessionFactory或hibernateTemplate
 */
public class HibernateBaseDao extends HibernateDaoSupport {
	private Log logger = LogFactory.getLog(HibernateBaseDao.class);

	/**
	 * 删除持久化对豄1�7
	 * 
	 * @param entity
	 *            持久化对豄1�7
	 */
	public void delete(Object entity) {
		getHibernateTemplate().delete(entity);
	}

	/**
	 * 删除扄1�7有的持久化对豄1�7
	 * 
	 * @param entities
	 *            持久化对豄1�7
	 */

	public void delete(Collection entities) {
		getHibernateTemplate().deleteAll(entities);
	}

	/**
	 * 执行回调接口
	 * 
	 * @param action
	 *            回调接口
	 * @return 执行结果
	 */
	public Object execute(HibernateCallback action) {
		return getHibernateTemplate().execute(action);
	}

	/**
	 * 执行回调查询
	 * 
	 * @param action
	 *            回调接口
	 * @return 查询结果列表
	 */

	public List executeFind(HibernateCallback action) {
		return getHibernateTemplate().executeFind(action);
	}

	/**
	 * 根据示例查询结果
	 * 
	 * @param <T>
	 * @param exampleEntity
	 *            示例对象
	 * @return 查询结果列表
	 */

	public List findByExample(Object exampleEntity) {
		return getHibernateTemplate().findByExample(exampleEntity);
	}

	/**
	 * 根据示例查询结果
	 * 
	 * @param <T>
	 * @param exampleEntity
	 *            示例对象
	 * @param firstResult
	 *            第一条结果的行数
	 * @param maxResult
	 *            结果集记录数可能的最大�1�7�1�7
	 * @return 查询结果列表
	 */

	public List findByExample(Object exampleEntity, int firstResult,
			int maxResult) {
		return getHibernateTemplate().findByExample(exampleEntity, -1, -1);
	}

	/**
	 * 根据hql语句查询结果
	 * 
	 * @param query
	 *            hql语句
	 * @return 查询结果列表
	 */

	public List findByQuery(String query) {
		return findByQuery(query, (Object[]) null);
	}

	/**
	 * 根据hql语句查询结果
	 * 
	 * @param query
	 *            hql语句
	 * @param value
	 *            第一丄1�7绑定参数
	 * @return 查询结果列表
	 */

	public List findByQuery(String query, Object value) {
		return findByQuery(query, new Object[] { value });
	}

	/**
	 * 根据hql语句查询结果
	 * 
	 * @param query
	 *            hql语句
	 * @param values
	 *            多个?绑定的参数数组1�7
	 * @return 查询结果列表
	 */
	public List findByQuery(String query, Object[] values) {
		return findByQuery(query, values, -1, -1);
	}

	/**
	 * 根据hql语句查询结果
	 * 
	 * @param query
	 *            hql语句
	 * @param values
	 *            多个?绑定的参数数组1�7
	 * @param firstResult
	 *            第一条结果的行数
	 * @param maxResult
	 *            结果集记录数可能的最大�1�7�1�7
	 * @return 查询结果列表
	 */
	public List findByQuery(String query, Object[] values, int firstResult,
			int maxResult) {
		return find(query, values, firstResult, maxResult, true);
	}

	/**
	 * 根据sql语句查询结果
	 * 
	 * @param query
	 *            sql语句
	 * @return 查询结果列表
	 */
	public List findBySQLQuery(String query) {
		return findBySQLQuery(query, (Object[]) null);
	}

	/**
	 * 根据sql语句查询结果
	 * 
	 * @param query
	 *            sql语句
	 * @param value
	 *            第一丄1�7绑定的参敄1�7
	 * @return 查询结果列表
	 */

	public List findBySQLQuery(String query, Object value) {
		return findBySQLQuery(query, new Object[] { value });
	}

	/**
	 * 根据sql语句查询结果
	 * 
	 * @param query
	 *            sql语句
	 * @param values
	 *            多个?绑定的参数数组1�7
	 * @return 查询结果列表
	 */
	public List findBySQLQuery(final String query, final Object[] values) {
		return findBySQLQuery(query, values, -1, -1);
	}

	/**
	 * 根据sql语句查询结果
	 * 
	 * @param query
	 *            sql语句
	 * @param values
	 *            多个?绑定的参数数组1�7
	 * @param firstResult
	 *            第一个结果的行数
	 * @param maxResult
	 *            结果集记录数可能的最大�1�7�1�7
	 * @return 查询结果列表
	 */
	public List findBySQLQuery(String query, Object[] values, int firstResult,
			int maxResult) {
		return find(query, values, firstResult, maxResult, false);
	}

	/**
	 * 根据hql或sql语句查询结果
	 * 
	 * @param query
	 *            sql或hql语句
	 * @param values
	 *            多个?绑定的参数数组1�7
	 * @param firstResult
	 *            第一个结果的行数
	 * @param maxResult
	 *            结果集记录数可能的最大�1�7�1�7
	 * @param isHql
	 *            是否为hql语句
	 * @return 查询结果列表
	 */
	final static ResultTransformer MapResultTransFormer = new MapResultTransFormer();

	protected List find(final String query, final Object[] values,
			final int firstResult, final int maxResult, final boolean isHql) {
		logger.debug("参数:[query]" + query + ",[values]"
				+ StringUtil.toString(values) + ",[firstResultF]" + firstResult
				+ ",[maxResult]" + maxResult + "[isHql]" + isHql);
		return (List) execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query queryObject = null;
				if (isHql)
					queryObject = session.createQuery(query);
				else {
					queryObject = session.createSQLQuery(query);
					queryObject.setResultTransformer(MapResultTransFormer);
				}
				prepareQuery(queryObject);
				if (firstResult > 0)
					queryObject.setFirstResult(firstResult);
				if (maxResult > 0)
					queryObject.setMaxResults(maxResult);
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						queryObject.setParameter(i, values[i]);
					}
				}
				return queryObject.list();
			}
		});
	}

	/**
	 * 根据hql语句查询丄1�7个结构1�7
	 * 
	 * @param query
	 *            hql语句
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	public Object findOneByQuery(final String query) {
		return findOneByQuery(query, (Object[]) null);
	}

	/**
	 * 根据hql语句查询丄1�7个结构1�7
	 * 
	 * @param query
	 *            hql语句
	 * @param value
	 *            第一丄1�7参数
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	public Object findOneByQuery(final String query, Object value) {
		return findOneByQuery(query, new Object[] { value });
	}

	/**
	 * 根据hql语句查询丄1�7个结构1�7
	 * 
	 * @param query
	 *            hql语句
	 * @param values
	 *            按顺序绑宄1�7的参数�1�7�1�7
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	public Object findOneByQuery(final String query, final Object[] values) {
		return findOne(query, values, true);
	}

	/**
	 * 根据sql语句查询丄1�7个结构1�7
	 * 
	 * @param query
	 *            sql语句
	 * @param value
	 *            第一丄1�7参数
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	public Object findOneBySQLQuery(final String query) {
		return findOneBySQLQuery(query, (Object[]) null);
	}

	/**
	 * 根据sql语句查询丄1�7个结构1�7
	 * 
	 * @param query
	 *            sql语句
	 * @param values
	 *            按顺序绑宄1�7的参数�1�7�1�7
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	public Object findOneBySQLQuery(final String query, Object value) {
		return findOneBySQLQuery(query, new Object[] { value });
	}

	/**
	 * 根据sql语句查询丄1�7个结构1�7
	 * 
	 * @param query
	 *            sql语句
	 * @param values
	 *            按顺序绑宄1�7的参数�1�7�1�7
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	public Object findOneBySQLQuery(final String query, final Object[] values) {
		return findOne(query, values, false);
	}

	/**
	 * @param query
	 *            sql或hql语句
	 * @param values
	 *            多个?绑定的参数数组1�7
	 * @param isHql
	 *            是否为hql语句
	 * @return 结果，若没有对应的结果则返回null〄1�7
	 */
	protected Object findOne(final String query, final Object[] values,
			final boolean isHql) {
		List list = find(query, values, -1, -1, isHql);
		if (list.isEmpty())
			return null;
		return list.get(0);
	}

	/**
	 * 存储数据对象
	 * 
	 * @param entity
	 *            霄1�7要存储的数据对象
	 * @return 数据对象的标识Id
	 */
	public Serializable save(Object entity) {
		return getHibernateTemplate().save(entity);
	}

	/**
	 * 更新持久化对豄1�7
	 * 
	 * @param entity
	 *            霄1�7要更新的持久化对豄1�7
	 */
	public void update(Object entity) {
		getHibernateTemplate().update(entity);
	}

	/**
	 * 通过hql语句更新数据库中的记彄1�7
	 * 
	 * @param query
	 *            hql语句
	 * @return 更新的记录条敄1�7
	 */
	public int updateByQuery(String query) {
		return getHibernateTemplate().bulkUpdate(query);
	}

	/**
	 * 通过hql语句更新数据库中的记彄1�7
	 * 
	 * @param query
	 *            hql语句
	 * @param value
	 *            第一丄1�7的绑定�1�7�1�7
	 * @return 更新的记录条敄1�7
	 */
	public int updateByQuery(String query, Object value) {
		return getHibernateTemplate().bulkUpdate(query, value);
	}

	/**
	 * 通过hql语句更新数据库中的记彄1�7
	 * 
	 * @param query
	 *            hql语句
	 * @param values
	 *            ?的绑定�1�7�数组1�7
	 * @return 更新的记录条敄1�7
	 */
	public int updateByQuery(String query, Object[] values) {
		return // getHibernateTemplate().bulkUpdate(query,values);
		update(query, values, true);
	}

	/**
	 * 通过sql语句更新数据库的记录
	 * 
	 * @param query
	 *            sql语句
	 * @param values
	 *            ?的绑定�1�7�数组1�7
	 * @return 被更新的记录条数
	 */
	public int updateBySQLQuery(String query, Object[] values) {
		return update(query, values, false);
	}

	/**
	 * 通过hql或sql语句更新数据库中的记彄1�7
	 * 
	 * @param query
	 *            hql或sql语句
	 * @param values
	 *            ?的绑定�1�7�数组1�7
	 * @param isHql
	 *            是否是hql语句
	 * @return 数据库中被更新的记录条数
	 */
	protected int update(final String query, final Object[] values,
			final boolean isHql) {
		Integer updateCount = (Integer) execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query queryObject = null;
				if (isHql)
					queryObject = session.createQuery(query);
				else
					queryObject = session.createSQLQuery(query);
				prepareQuery(queryObject);
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						queryObject.setParameter(i, values[i]);
					}
				}
				return new Integer(queryObject.executeUpdate());
			}
		});
		return updateCount.intValue();
	}

	/**
	 * 预处理Query,含是否缓存处理，fetchSize设置，及maxResults设置和事务超时处琄1�7
	 * 
	 * @param queryObject
	 *            hibernate Query对象
	 */
	protected void prepareQuery(Query queryObject) {
		if (getHibernateTemplate().isCacheQueries()) {
			queryObject.setCacheable(true);
			if (getHibernateTemplate().getQueryCacheRegion() != null) {
				queryObject.setCacheRegion(getHibernateTemplate()
						.getQueryCacheRegion());
			}
		}
		SessionFactoryUtils.applyTransactionTimeout(queryObject,
				getHibernateTemplate().getSessionFactory());
	}
}
